import axios from "axios";
import router from "@/router";
import Qs from "qs";
import type {AxiosResponse, InternalAxiosRequestConfig, AxiosInstance} from 'axios'
import {ElMessage, ElNotification, ElMessageBox} from 'element-plus'
import {useCounterStore} from "@/store/counter";
import {getToken} from "@/utils/auth";

const useRequest: AxiosInstance = axios.create({
    baseURL: import.meta.env.VITE_APP_LOGIN_URL,
    timeout: 10000,
    headers: {'Content-Type': 'application/json;charset=utf-8'}
})

const errorCode: Record<string, string> = {
    '401': '认证失败，无法访问系统资源',
    '403': '当前操作没有权限',
    '404': '访问资源不存在',
    'default': '系统未知错误，请反馈给管理员'
}
// @ts-ignore
useRequest.interceptors.request.use((request: InternalAxiosRequestConfig) => {
    // 是否需要设置 token
    if (getToken()) {
        request.headers['token'] = 'Bearer ' + getToken()
    }
    return request
}, error => {
    Promise.reject(error)
})

// @ts-ignore
useRequest.interceptors.response.use((res: AxiosResponse) => {
        const code = res.data.code || 200;
        const msg = errorCode[code] || res.data.message || errorCode['default']
        if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
            return res.data
        }
        if (code === 401) {
            ElMessage({message: '登录状态已过期，请重新登录。', type: 'warning'})
            ElMessageBox.confirm('登录状态已过期，您可以继续留在该页面，或者重新登录', '系统提示', {
                confirmButtonText: '重新登录',
                cancelButtonText: '取消',
                closeOnClickModal: false,
                type: 'warning'
            }).then(() => {
                const store: any = useCounterStore()
                store.logOut().then(() => {
                    router.go(0);
                })
            }).catch(() => {
            })
            return Promise.reject('无效的会话，或者会话已过期，请重新登录。')
        } else if (code === 500) {
            ElMessage({message: msg, type: 'error'})
            return Promise.reject(new Error(msg))
        } else if (code === 601) {
            ElMessage({message: msg, type: 'warning'})
            return Promise.reject(new Error(msg))
        } else if (code !== 200) {
            ElNotification.error({title: msg})
            return Promise.reject('error')
        } else {
            return Promise.resolve(res.data)
        }

    },
    error => {
        let {response, message} = error;
        if (response.config.url != '/getBindWeb') {
            if (message == "Network Error") {
                message = "后端接口连接异常";
            } else if (message.includes("timeout")) {
                message = "系统接口请求超时";
            } else if (message.includes("Request failed with status code")) {
                message = "系统接口" + message.substr(message.length - 3) + "异常";
            }
            ElMessage({message: message, type: 'error', duration: 5 * 1000})
            return Promise.reject(error)
        }
    })

class baseRequest {
    qspost(url: string, data?: mapType): Promise<AxiosResponse<any, any>> {
        return new Promise((resolve, reject): void => {
            useRequest.post(url, Qs.stringify(data)).then(res => {
                resolve(res)
            }).catch((): void => {
            })
        })
    }

    post(url: string, data?: mapType): Promise<AxiosResponse<any, any>> {
        return new Promise((resolve, reject): void => {
            useRequest.post(url, data).then(res => {
                resolve(res)
            }).catch((): void => {
            })
        })
    }

    get(url: string, params?: mapType): Promise<AxiosResponse<any, any>> {
        return new Promise((resolve, reject): void => {
            useRequest.get(url, {params}).then(res => {
                resolve(res)
            }).catch((): void => {
            })
        })
    }

    put(url: string, params?: mapType): Promise<AxiosResponse<any, any>> {
        return new Promise((resolve, reject): void => {
            useRequest.put(url, params).then(res => {
                resolve(res)
            }).catch((): void => {
            })
        })
    }

    delete(url: string, params?: mapType): Promise<AxiosResponse<any, any>> {
        return new Promise((resolve, reject): void => {
            useRequest.delete(url, {params}).then(res => {
                resolve(res)
            }).catch((): void => {
            })
        })
    }
}

export default new baseRequest()
